昨天我們增加了一個地址的檔案怪物
如果這些放在元件裡面 會很恐怖的吧
剛好之前其實就有想把main的設定檔抽取出來
這樣我們來做個mock-data吧
首先即使我們要做mock-data
也是要模擬打api的行為
這樣我們做個data.service在share/service之下
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class DataService
{
private jsonUrl = 'assets/mock/main-data.json';
constructor(private http: HttpClient) { }
getMainData(): Observable<any>
{
return this.http.get(this.jsonUrl);
}
}
然後把原本main的設定檔搬到assets/mock/main-data.json之下
{
"pageSettings": [
{
"title": "第一頁",
"fieldSettings": [
{
"name": "addressCity",
"cname": "地址",
"inputType": "select",
"groupName": "address1",
"groupType": "address-city",
"options": []
},
...以下省略
原本main的地方改成在ngInit的時候讀取
pageSettings!: PageSetting[]
constructor(private dataService: DataService) { }
ngOnInit(): void
{
this.dataService.getMainData().subscribe(data =>
{
this.pageSettings = data.pageSettings;
})
}
不過這樣調整會有問題
原本validator的陣列我們是直接使用原生的Validator
改成json後會失效
這樣我們調整成用"required" "maxLength:3"這樣的關鍵字去紀錄
在讀取設定檔轉換成form的時候再調整
//form-input.component.ts
let newControl = this.fb.control(setting.defaultValue) as FormControl;
if (setting.validator && setting.validator?.length > 0)
{
setting.validator?.forEach((v: string) =>
{
let keyword = v.split(':')
switch (keyword[0])
{
case 'required':
setting.required = true;
newControl.addValidators(Validators.required);
break;
case 'maxLength':
newControl.addValidators(Validators.maxLength(Number(keyword[1])));
break;
}
})
}
原本let newControl會直接使用setting.validator
這邊變成下面跑回圈去addValidators
然後剛剛API的部分畢竟是模擬
考慮到日後可能會真的接API
我們把mock的部分轉移到intercept裡面
創建mock.interceptor
import { Injectable } from '@angular/core';
import
{
HttpRequest,
HttpHandler,
HttpEvent,
HttpInterceptor
} from '@angular/common/http';
import { Observable } from 'rxjs';
import { environment } from 'src/environments/environment';
@Injectable()
export class MockInterceptor implements HttpInterceptor
{
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>>
{
// 判斷是否啟用 mock
if (environment.isMock)
{
// 如果是 mock,將請求重定向到本地 JSON 文件
const mockReq = req.clone({
url: `assets/mock/${req.url}-data.json` // 假設所有本地 JSON 文件存放在 assets/mocks 中
});
return next.handle(mockReq);
} else
{
// 否則繼續使用原本的 URL
return next.handle(req);
}
}
}
這邊攔截Http 如果isMock 那就指向到本地文件
這邊有調整到環境變數
//environment.ts
export const environment = {
production: false,
isMock: true //增加這個
};
data.service會調整一下 再加上地址的部分會是這樣
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class DataService
{
// private jsonUrl = 'assets/mock/main-data.json';
constructor(private http: HttpClient) { }
getMainData(): Observable<any>
{
// return this.http.get(this.jsonUrl);
return this.http.get('main');
}
getAddressData(): Observable<any>
{
// return this.http.get(this.jsonUrl);
return this.http.get('address');
}
}
這樣調整就方便日後擴充
也方便開關 很棒吧
今日程式:day22